package com.itbac.shiro.realm;

import com.itbac.shiro.service.impl.SecurityServiceImpl;
import com.itbac.shiro.utils.DigestsUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.List;
import java.util.Map;

/**
 * 自定义Real安全域 ,重写认证授权方法。
 * @author: BacHe
 * @email: 1218585258@qq.com
 * @Date: 2020/12/27 16:38
 */
public class MyRealm extends AuthorizingRealm{

    //构造函数，设置密码匹配器
    public MyRealm() {
        //设置加密算法
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);
        //指定密码迭代次数
        matcher.setHashIterations(DigestsUtil.ITBRATIONS);
        //调用父类中的方法，使匹配方式生效
        setCredentialsMatcher(matcher);
    }

    /**
     * 鉴权方法
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //拿到用户凭证信息   Primary Principal 主要 负责人
        String loginName = (String) principalCollection.getPrimaryPrincipal();
       //模拟查询数据库
        SecurityServiceImpl securityService = new SecurityServiceImpl();
        //查询角色
        List<String> roles = securityService.findRoleByLoginName(loginName);
        //查询权限
        List<String> permission = securityService.findPermissionByLoginName(loginName);
        //封装包装类返回
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roles);
        info.addStringPermissions(permission);
        return info;
    }


    /**
     * 认证方法
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //从token获取登录名
        String loginName = (String) authenticationToken.getPrincipal();
        //模拟查询数据库
        SecurityServiceImpl securityService = new SecurityServiceImpl();
        Map<String, String> map = securityService.getPasswordByUserName(loginName);
        if (null == map || map.isEmpty()) {
            throw new AuthenticationException(String.format("账号[%s]不存在", loginName));
        }
        System.out.println("getName():" + getName());
        //getName():myrealm666
        String salt = map.get("salt");
        String password = map.get("password");
        System.out.println("map:"+map);


        /**
         * 构建简单的身份验证信息对象
         *
         * @param loginName 真实账号  principal
         * @param password  真实密码(密文) credentials
         * @param credentialsSalt  盐
         * @param getName() shiro2.ini文件中声明的：myrealm666
         */
        return new SimpleAuthenticationInfo(loginName, password, ByteSource.Util.bytes(salt), getName());
    }

}
